#!/usr/bin/python
import unittest
import sys
import os
from StringIO import StringIO
import tempfile
import re

# Import app modules
from uya.routerconf.configmod import generic
#import common

class TestGeneric(unittest.TestCase):        

    def create_temporal(self, data=None):
        """Create a temporal file path."""
        fd, path = tempfile.mkstemp()
        if data:
            os.write(fd, data)
        os.close(fd)
        return path

    def test_run(self):
        text = "hola"
        command = ["echo", text]
        returncode, output, error = generic.run(command)
        self.assertEqual(0, returncode) 
        self.assertEqual(text, output.strip()) 

    def test_mkdir(self):
        path = "/tmp/configmod.%s" % os.getpid()
        generic.mkdir(path)
        self.assertTrue(os.path.isdir(path))
        generic.mkdir(path)
        os.rmdir(path)
        
    def test_str2re(self):
        s = "$hola = [^1+]?"
        escaped = generic.str2re(s)
        self.assertEqual(r"\$hola = \[\^1\+\]\?", escaped)                

    def test_readlines(self):
        content = "line1\nline2\n"
        path = self.create_temporal(content)
        self.assertEqual(["line1\n", "line2\n"], generic.readlines(path))
        os.unlink(path)
        self.assertEqual([], generic.readlines(path))
        
    def test_getstring_sequence(self):
        data = generic.getstring(["line1 2", "line2"])
        self.assertEqual("line1 2\nline2\n", data)
        
    def test_getstring_string(self):
        data = generic.getstring("line1 2\nline2\n")
        self.assertEqual("line1 2\nline2\n", data)
        
    def test_write_lines(self):
        path = self.create_temporal()
        dataseq = ["line1", "line2"]
        generic.write_lines(path, dataseq)
        self.assertEqual("line1\nline2\n", open(path).read())
        os.unlink(path)        

    def test_overwrite_file(self):
        path = self.create_temporal("content\n")
        overwrite = generic.overwrite_file(path, ["new_content"])
        self.assertEqual("new_content\n", open(path).read())
        self.assertTrue(overwrite)
        overwrite = generic.overwrite_file(path, ["new_content"])
        self.assertFalse(overwrite)
        os.unlink(path)
        
    def test_update_variables(self):
        old = [
            ("a", "1"),
            ("# comment", ""),
            ("  b", "3"),
        ]
        variables = [
            ("a", "newa"),
            ("c", "4"),
        ]
        expected = [
            ("a", "newa"),
            ("# comment", ""),
            ("  b", "3"),
            ("  c", "4"),
        ] 
        new = generic.update_variables(old, variables)
        self.assertEqual(expected, new)

    def test_update_variables_with_list(self):
        old = [
            ("a", "1"),
            ("a", "2"),
            ("# comment", ""),
            ("  b", "3"),
        ]
        variables = [
            ("a", ["1", "1a"]),
            ("c", "4"),
        ]
        expected = [
            ("a", "1"),
            ("a", "1a"),
            ("# comment", ""),
            ("  b", "3"),
            ("  c", "4"),
        ] 
        new = generic.update_variables(old, variables)
        self.assertEqual(expected, new)
         
    def test_update_variables_plain(self):
        
        original_testscript = """
A=1
# comment
B="2"
  C=hola
"""

        expected_testscript = """
A="newA"
# comment
B="2"
  C="newC"
  D="newD_keeping_indent"
"""

        update_variables = [
            ("A", "newA"),
            ("C", "newC"),
            ("D", "newD_keeping_indent"),
        ]            
        
        path = self.create_temporal(original_testscript)
        output = generic.update_variables_plain(
            original_testscript.splitlines(), update_variables, 
            assignation='\s*([^=]+)="?(.*?)"?\s*$', output_format='%s="%s"')
        self.assertEqual(expected_testscript.splitlines(), list(output))
           
    def test_update_variables_with_sections(self):
        original = """
x 1

section 1
    a 1
    b 2

special 2 x 0
    c 3

section 4
    e 5    
"""        
        expected = """x 1new
y 6
y 7

section 1
    a 1
    b 2new

special 2 y 1
    c 3
    c2 c2new

section 4
    e 5

section 3
    d 4
    d 5
"""
        
        update_variables = [
            (None, [
                ("x", "1new"),
                ("y", ["6", "7"]),
            ]),                
            ("section 1", [
                ("b", "2new"),
            ]),
            ("special 2 y 1", [
                ("c2", "c2new"),
            ]),
            ("section 3", [
                ("d", ["4", "5"]),
            ]),
        ]
        
        new = generic.update_variables_with_sections(
            original.splitlines(), 
            update_variables, 
            section_assignation="^\s*(section \w|special \w)\s*(.*)\s*$",
            variable_assignation='\s*([^\s]+)\s+(.*)\s*$',
            output_format="%s %s", section_indenting=" "*4)
        self.assertEqual(expected, new)     

    def test_get_items(self):
        input_items = [
            ("abc_h_1", "hello"),
            ("ad_x", "bye"),
            ("abc_h_2", "test"),
        ]
        expected_items = [
            ("h_1", "hello"),
            ("h_2", "test"),
        ]
        items = generic.get_items(input_items, "abc_h", "abc_")
        self.assertEqual(expected_items, list(items))

    def XXXtest_update_variables_with_sections2(self):
        original = """
z 0
a 1
b 2
c u 3 4

sect 1 x y
    m 1
    n 2

anothersect
    k e 5

d 5"""        
        expected = """
z 0
a 11
c u 33 44

sect 1 x z
    m 1
    n 22
    n 23

d 5

sect 2 l m
    j 33
    
new1 1"""        
        update_variables = [
            ("new1", "1"), 
            ("a", "11"),
            ("b", None),
            ("c u", "33 44"),
            ("sect 1 x z", [
                ("n", ["22", "23"]),
            ]),
            ("sect 2 l m", [
                ("j", "33"),
            ]),
            ("anothersect", None),
            ("d", "55"),                        
        ]

        section_regexp = re.compile(r"""
        \s*(
            sect\s+\w+ |
            anothersect |
            z           |
            a           |
            b           |
            c\s+u       |
            d           |             
        )\s*(.*)\s*$""", re.VERBOSE)
        
        variables_regexp = re.compile(r"""
        \s*( 
            z       |
            a       |
            b       |           
            c\s+u   |
            k\s+e   |
            d       
            [^\s]+
        )\s+(.*)\s*$""", re.VERBOSE) 
                    
        new = generic.update_variables_with_sections2(
            original.splitlines(), 
            update_variables, 
            section_assignation=section_regexp,
            section_format="%s %s",
            variable_assignation=variables_regexp,
            variable_format="%s %s", 
            section_indenting=" "*4,
        )
        self.assertEqual(expected.splitlines(), new)            
        #self.assertEqualSeqs(expected.splitlines(), new)     

def suite():
    return unittest.TestLoader().loadTestsFromTestCase(TestGeneric)
                 
if __name__ == '__main__':
    unittest.main(testRunner=unittest.TextTestRunner(verbosity=2))
